package calao;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Locale;

import calao.util.xml.XmlWriter;

public abstract class HtmlPage 
{
	
	enum ScriptType 
	{ 
		JAVASCRIPT("text/javascript");
		final String mimeType;
		ScriptType(String mimeType)
		{
			this.mimeType = mimeType;
		}
		String getMimeType()
		{
			return mimeType;
		}
	};
	
	private XmlWriter xwriter;
	
	final void writeTo(Writer writer)
	throws IOException
	{
		this.xwriter = new XmlWriter(writer);
		writePage();
	}	
	
	void writePage()
	throws IOException
	{
		xwriter.startElement("html");
		xwriter.startElement("head");
		writeHead();
		xwriter.endElement();
		xwriter.startElement("body");
		writeBody();
		xwriter.endElement();
		xwriter.endElement();		
	}
	
	void setOutput(OutputStream stream)
	{
		this.xwriter = new XmlWriter(new OutputStreamWriter(stream));
	}
	
	abstract void writeBody()
	throws IOException;
	
	abstract void writeHead()
	throws IOException;
	
	void writeTitle(String title)
	throws IOException
	{
		xwriter.startElement("title");
		xwriter.write(title);
		xwriter.endElement();
	}
	
	void startForm(String action, String method)
	throws IOException
	{
		xwriter.startElement("form",  "method", method, "action", action);		
	}
	
	void endElement()
	throws IOException
	{
		xwriter.endElement();
	}
	
	void startTable(String align)
	throws IOException
	{
		xwriter.startElement("table", "align", align);
	}
	
	void startCenteredTable()
	throws IOException
	{
		startTable("center");
	}

	void startTable()
	throws IOException
	{
		startTable(null);
	}

	void startRow()
	throws IOException
	{
		xwriter.startElement("tr");
	}
		
	void startCell()
	throws IOException
	{
		xwriter.startElement("td");
	}
	
	void write(String text)
	throws IOException
	{
		xwriter.write(text);
	}
	
	void writeInput(String type, String name)
	throws IOException
	{
		writeInput(type, name, null);
	}
	
	void startDiv(String id)
	throws IOException
	{
		startElement("div", "id", id);
	}
	
	void startScript(ScriptType type)
	throws IOException
	{
		startElement("script", "type", type.getMimeType());
	}
	
	void writeInput(String type, String name, String value)
	throws IOException
	{
		xwriter.writeElement("input", "type", type, "name", name, "value", value);
	}

	@SuppressWarnings("unchecked")
	static <T extends HtmlPage> T getPage(Class<T> pclass, Locale locale)
	{
		try {
			Class lpclass = Class.forName(pclass.getName()+"_"+locale.getLanguage());
			if (pclass.isAssignableFrom(lpclass)) return (T)lpclass.newInstance();
		} 
		catch (ClassNotFoundException e) { } 
		catch (Exception e) {
			throw new RuntimeException(e);
		} 
		// defaults to base class
		try {
			return pclass.newInstance();
		}
		catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	void writeStyleSheetLink(String href)
	throws IOException
	{
		xwriter.writeElement("link", "rel", "stylesheet", "type", "text/css", 
				"href", href);		
	}
	
	void writeMeta(String name, String content)
	throws IOException
	{
		xwriter.writeElement("meta", "name", name, "content", content);
	}
	
	void includeScript(ScriptType type, String src)
	throws IOException
	{
		xwriter.startElement("script", "type", type.getMimeType(),
				"src", src);
		xwriter.endElement();		
	}
	
	void startElement(String name, String... avPairs)
	throws IOException
	{
		xwriter.startElement(name, avPairs);
	}
	
	void flushOutput()
	throws IOException
	{
		xwriter.flush();
	}

}
